import com.sun.xml.internal.ws.util.StringUtils;
import freemarker.template.Template;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述：代码生成器
 * Created by Ay on 2017/5/1.
 */
public class CodeGenerateUtils {
    private final String AUTHOR = "yeyongjian";
    private final String CURRENT_DATE = new Date().toLocaleString();
    private final String tableAnnotation = "";
//private final String[] tableNames = new String[]{"t_order"
//};
private final String[] tableNames = new String[]{
        "orders_product"
//"t_group_order_refund"
};

    private final String API = "com.sibu.shop.api";
    private final String ADMIN = "com.sibu.shop.admin";
    private final String PLAT = "com.sibu.shop.plat";
    private final String PROJCET = API;
    private final String COMMON_MODEL = "com.sibu.shop.common.model";
    private final String packet = ".logistics";
    private final String requestPackageName = PROJCET+".request"+packet;
    private final String responsePackageName = PROJCET+".response"+packet;
    private final String daoPackageName = PROJCET+".persistence.dao"+packet;
    private final String serviceInterfacePackageName = PROJCET+".service"+packet;
    private final String serviceImplPackageName = PROJCET+".service.impl"+packet;
    private final String controllerPackageName = PROJCET+".web.controller"+packet;
    private final String modelPackageName = COMMON_MODEL;



//    private final String URL = "jdbc:mysql://localhost:3306/sibu_shop";
//    private final String USER = "root";
//    private final String PASSWORD = "root";
//    private final String URL = "jdbc:mysql://120.76.190.48/sibu_shop";
//    private final String USER = "sibu_wesale";
//    private final String PASSWORD = "emIFhtPc6tKiniwfvNC6";
    private final String URL = "jdbc:mysql://localhost:3306/world";
    private final String USER = "root";
    private final String PASSWORD = "root";
//    private final String URL = "jdbc:mysql://172.16.10.16:3306/mall_base";
//    private final String USER = "sibu_develop_write";
//    private final String PASSWORD = "LU8%**DZYbZ7*c85";
//    private final String URL = "jdbc:mysql://118.89.51.164:3306/ejavashop";
//    private final String USER = "sibu_wesale";
//    private final String PASSWORD = "6SvbL5+JhXQSpf+ASsQ0Rg==";

//    private final String URL = "jdbc:mysql://localhost:3306/yyj_user";
//    private final String USER = "root";
//    private final String PASSWORD = "root";
    private final String DRIVER = "com.mysql.jdbc.Driver";

    private final String diskPath = "D:\\projectCodeing\\fremark\\dest\\";

    private  String changeTableName = "orders_product";
    private  String tableName = "orders_product";

    public Connection getConnection() throws Exception{
        Class.forName(DRIVER);
        Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
        return connection;
    }

    public static void main(String[] args) throws Exception{
        CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
        codeGenerateUtils.deleFiles();
        codeGenerateUtils.generate();
    }


    public void deleFiles() throws Exception{
        File file = new File(diskPath);
        List<File> list = findFiles(file);
        list.forEach(f->{
            f.delete();
        });
    }
    public List<File> findFiles(File file) throws Exception{
        List<File> list = new ArrayList<File>();
        File[] files = file.listFiles();
        if(files.length==0){
            return new ArrayList<File>();
        }
        for (int i = 0 ; i <files.length;i++){
            if(files[i].isFile()){
                list.add(files[i]);
            }else {
                List<File> nextFiles = findFiles(files[i]);
                list.addAll(nextFiles);
            }
        }
        return list;
    }
    public void generate() throws Exception{
        try {
            Connection connection = getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            for (String table: tableNames) {
                tableName = table;
//                tableName = table.substring(2,table.length());
                changeTableName = replaceUnderLineAndUpperCase(tableName);
                ResultSet resultSet = databaseMetaData.getColumns(null,"%", table,"%");

                //遍历resuletSet,干一些事
                Map<String,Object> dataMap = new HashMap();
                dataMap.put("ori_table",table);
                this.restltSet2JavaList(resultSet,dataMap);



                dataMap.put("service_impl_package_name",serviceImplPackageName);
                dataMap.put("service_interface_package_name",serviceInterfacePackageName);
                dataMap.put("response_package_name",responsePackageName);
                dataMap.put("request_package_name",requestPackageName);
                dataMap.put("dao_package_name",daoPackageName);
                dataMap.put("controller_package_name",controllerPackageName);
                dataMap.put("common_model",COMMON_MODEL);

                generateControllerFile(dataMap);
 /**/
                //生成ServiceInterface文件
                generateServiceInterfaceFile(dataMap);
                //生成ServiceImpl文件
                generateServiceImplFile(dataMap);

                //生成Mapper文件
                generateMapperFile(dataMap);
                //生成Dao文件
                generateDaoFile(dataMap);
                //生成Request文件
                generateRequestFile(dataMap);
                //生成Request文件
                generateResponseFile(dataMap);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally{

        }
    }

    private void generateResponseFile( Map<String,Object> dataMap) throws Exception {
        final String suffix = ".java";
        final String path = diskPath + "response\\"+changeTableName+"Response" + suffix;
        final String templateName = "Response.ftl";
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
        final String modelPath = diskPath + "model\\"+changeTableName+"" + suffix;
        final String modelTemplateName = "Model.ftl";
        File modelMapperFile = new File(modelPath);
        generateFileByTemplate(modelTemplateName,modelMapperFile,dataMap);
    }


    private void generateRequestFile(Map<String,Object> dataMap) throws Exception{
        //生成普通的request
        final String suffix = ".java";
        final String path = diskPath + "request\\"+changeTableName+"Request" + suffix;
        final String templateName = "Request.ftl";
        File mapperFile = new File(path);

        //生成分页pageRequest
        generateFileByTemplate(templateName,mapperFile,dataMap);
        final String pathPage = diskPath + "request\\"+changeTableName+"PageRequest" + suffix;
        final String templateNamePage = "PageRequest.ftl";
        mapperFile = new File(pathPage);
        generateFileByTemplate(templateNamePage,mapperFile,dataMap);

    }


    private void generateControllerFile(Map<String,Object> dataMap) throws Exception{
        final String suffix = "Controller.java";
        final String path = diskPath +"controller\\"+ changeTableName + suffix;
        final String templateName = "Controller.ftl";
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    private void generateServiceImplFile(Map<String,Object> dataMap) throws Exception{
        final String suffix = "ServiceImpl.java";
        final String path = diskPath +"impl\\"+ changeTableName + suffix;
        final String templateName = "ServiceImpl.ftl";
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    private void generateServiceInterfaceFile(Map<String,Object> dataMap) throws Exception{
        final String suffix = "Service.java";
        final String path = diskPath +"service\\"+ changeTableName + suffix;
        final String templateName = "ServiceInterface.ftl";
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }


    private void generateDaoFile(Map<String,Object> dataMap) throws Exception{
        final String suffix = "WriteDao.java";
        final String path = diskPath +"dao\\"+ changeTableName + suffix;
        final String templateName = "DAO.ftl";
        File mapperFile = new File(path);

        generateFileByTemplate(templateName,mapperFile,dataMap);

    }
    private void generateMapperFile(Map<String,Object> dataMap) throws Exception {
        final String suffix = "Mapper.xml";
        final String path = diskPath +"mapper\\"+ changeTableName + suffix;
        final String templateName = "Mapper.ftl";
        File mapperFile = new File(path);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small",tableName);
        dataMap.put("table_name",changeTableName);
        dataMap.put("author",AUTHOR);
        dataMap.put("date",CURRENT_DATE);

        dataMap.put("table_annotation",tableAnnotation);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
    }

    public String replaceUnderLineAndUpperCase(String str){
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while(count!=0){
            int num = sb.indexOf("_",count);
            count = num + 1;
            if(num != -1){
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count , count + 1,ia + "");
            }
        }
        String result = sb.toString().replaceAll("_","");
        return StringUtils.capitalize(result);
    }

    /**
     * restltSet转为JavaList
     * @param resultSet
     * @return
     */
    private List<ColumnClass> restltSet2JavaList(ResultSet resultSet,Map<String,Object> dataMap) {
        List<ColumnClass> columnClassList = new ArrayList();
        Boolean hasShopId = false;
        Boolean hasUid = false;
        Boolean deleteFlag = false;
        ColumnClass columnClass = null;
        try {
            while(resultSet.next()){
                //id字段略过
                //            if(resultSet.getString("COLUMN_NAME").equals("id")) continue;
                columnClass = new ColumnClass();
                //获取字段名称
                columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
                //获取字段类型
                columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
                //转换字段名称，如 sys_name 变成 SysName
                columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
                //字段在数据库的注释
                columnClass.setColumnComment(resultSet.getString("REMARKS"));

                if(columnClass.getColumnName().equals("shop_id")){
                    hasShopId = true ;
                    dataMap.put("shop_id_column_type",columnClass.getColumnType());
                }
                if(columnClass.getColumnName().equals("uid")){
                    hasUid = true ;
                    dataMap.put("uid_column_type",columnClass.getColumnType());
                }
                if(columnClass.getColumnName().equals("delete_flag")){
                    deleteFlag = true ;
                    dataMap.put("delete_flag_column_type",columnClass.getColumnType());
                }
                columnClassList.add(columnClass);
            }
            dataMap.put("model_column",columnClassList);
            dataMap.put("content_shop_id",hasShopId);
            dataMap.put("content_uid",hasUid);
            dataMap.put("content_delete_flag",deleteFlag);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return columnClassList;
    }

}